#include "pch.h"
#include "framework.h"
#include "afxdialogex.h"
#include "tools.h"

#include "windows.h"
#pragma data_seg("Shared")

LPVOID ThreadAdd = NULL;
LPVOID ParamAdd = NULL;
const DWORD wSize = 1024 * 4;

// 将某个值写入植物大战僵尸内存（后面的可变参数是地址链，要以-1结尾）
void Tools::WriteMemory(HANDLE& g_processHandle, void* value, DWORD valueSize, ...) {
	if (value == NULL || valueSize == 0 || g_processHandle == NULL) return;

	DWORD tempValue = 0;

	va_list addresses;
	// 获取第一个valueSize的值为要写入的字节数
	va_start(addresses, valueSize);
	DWORD offset = 0;
	DWORD lastAddress = 0;
	while ((offset = va_arg(addresses, DWORD)) != -1) {
		lastAddress = tempValue + offset;
		// 1. 进程句柄 2. 内存地址 3. 接收的内容，缓冲区指针 4. 读取字节数 5. 指向传输到指定缓冲区的字节数的指针
		::ReadProcessMemory(g_processHandle, (LPCVOID)lastAddress, &tempValue, sizeof(DWORD), NULL);
	}
	va_end(addresses);

	::WriteProcessMemory(g_processHandle, (LPVOID)lastAddress, value, valueSize, NULL);
}

void Tools::WriteMemory(HANDLE& g_processHandle, void* value, DWORD valueSize, DWORD address) {
	WriteMemory(g_processHandle, value, valueSize, address, -1);
}


void Tools::ChangeMemory(HANDLE& g_processHandle, CButton& button, DWORD address, void* value_orign, void* value_change, DWORD valueSize) {
	if (button.GetCheck()) {
		WriteMemory(g_processHandle, value_change, valueSize, address);
	}
	else {
		WriteMemory(g_processHandle, value_orign, valueSize, address);
	}
}



int MoneyPlus(LPVOID lParam) {
    Tools::paramdata* data = (Tools::paramdata*)lParam;
    __asm
    {
        mov eax, [0x006A9EC0]
        mov eax, [eax + 0x768]
        add [eax + 0x5560], 0x1F4
        ret
    }
    return 0;
}

void Tools::DoFunc(HANDLE& pid, void* funcptr, Tools::paramdata pdata)  //选择函数
{
    HANDLE TmpHandle;
    ::WriteProcessMemory(pid, ParamAdd, &pdata, sizeof(pdata), NULL);//将要注入的参数写到上面建立的内存空间中
    ::WriteProcessMemory(pid, ThreadAdd, funcptr, wSize, NULL);//将要注入的过程写到上面建立的内存空间中
    TmpHandle = ::CreateRemoteThread(pid, NULL, 0, (LPTHREAD_START_ROUTINE)ThreadAdd, ParamAdd, 0, NULL);
    //获得注入后过程的句柄ID
    ::ResumeThread(TmpHandle);      //运行注入的CALL线程
    ::WaitForSingleObject(TmpHandle, INFINITE);     //等待线程结束
    ::CloseHandle(TmpHandle);        //关闭线程
}

// pid: 进程 mkeycode: true为开辟内存, false为注销内存
void Tools::AllocMemory(HANDLE& pid, BOOL mkeycode)
//可导出函数，用于其他函数声明
{
    if (mkeycode) {
        //申请内存
        ThreadAdd = ::VirtualAllocEx(pid, NULL, wSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//在目标进程建立内存空间
        ParamAdd = ::VirtualAllocEx(pid, NULL, sizeof(paramdata), MEM_COMMIT, PAGE_READWRITE);//在目标进程建立内存空间
    }
    else {
        //释放内存
        if (ThreadAdd != NULL) ::VirtualFreeEx(pid, ThreadAdd, wSize, MEM_RELEASE);
        if (ParamAdd != NULL) ::VirtualFreeEx(pid, ParamAdd, sizeof(paramdata), MEM_RELEASE);
        if (ThreadAdd != NULL) ::VirtualFreeEx(pid, ThreadAdd, wSize, MEM_RELEASE);
        if (ParamAdd != NULL) ::VirtualFreeEx(pid, ParamAdd, sizeof(paramdata), MEM_RELEASE);
    }
}

// 模仿ce的代码注入工作
void Tools::CodeInjection(HANDLE& pid, BOOL mkeycode)
{
    //申请内存
    ThreadAdd = ::VirtualAllocEx(pid, NULL, wSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//在目标进程建立内存空间
    if (mkeycode) {
        
    }
    else {
        //释放内存
        if (ThreadAdd != NULL) ::VirtualFreeEx(pid, ThreadAdd, wSize, MEM_RELEASE);
        if (ParamAdd != NULL) ::VirtualFreeEx(pid, ParamAdd, sizeof(paramdata), MEM_RELEASE);
        if (ThreadAdd != NULL) ::VirtualFreeEx(pid, ThreadAdd, wSize, MEM_RELEASE);
        if (ParamAdd != NULL) ::VirtualFreeEx(pid, ParamAdd, sizeof(paramdata), MEM_RELEASE);
    }
}
